home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
lib
/
c
/
etc
/
Pdev.man
< prev
next >
Wrap
Text File
|
1990-06-27
|
21KB
|
491 lines
' $Header: /sprite/src/lib/c/etc/RCS/Pdev.man,v 1.5 90/03/30 15:47:27 douglis Exp $ SPRITE (Berkeley)
.so \*(]ltmac.sprite
.HS Pdev lib
.BS
.SH NAME
Pdev_Open, Pdev_Close, Pdev_SetDefaultHandler, Pdev_SetStreamHandler, Pdev_EnumStreams \- Package for servicing pseudo-devices.
.SH SYNOPSIS
\fB#include <pdev.h>\fR
.sp
Pdev_Token
.br
\fBPdev_Open\fR(\fIname, realNamePtr, reqBufSize, readBufSize, service, clientData\fR)
.br
void
.br
\fBPdev_Close\fR(\fIpdevToken\fR)
.br
int
.br
\fBPdev_GetStreamID\fR(\fIpdevToken\fR)
.br
int (*
.br
\fBPdev_SetDefaultHandler\fR(\fIpdevToken, operation, handler\fR))()
.br
int (*
.br
\fBPdev_SetStreamHandler\fR(\fIstreamPtr, operation, handler\fR))()
.br
int
.br
\fBPdev_EnumStreams\fR(\fIpdevToken, func, clientData\fR)
.SH ARGUMENTS
.AS Pdev_CallBacks readBufSize
.AP char *name in
Name of file to use for pseudo-device.
.AP char **realNamePtr out
Where to store pointer to actual pseudo-device file name, or NULL
if \fIname\fR is to be the complete name of pseudo-device file.
.AP int reqBufSize in
The preferred size for request buffers.
.AP int readBufSize in
The size for a read buffer. Zero means no read buffering.
.AP Pdev_CallBacks *service in
A set of service call-back procedures.
.AP ClientData clientData in
Private user-defined data field.
.AP Pdev_Token pdevToken in
Token for the pseudo-device returned from \fBPdev_Open\fP.
.AP Pdev_Stream *streamPtr in
Handle for a stream to the pseudo-device.
.AP int operation in
\fBPDEV_OPEN\fP, \fBPDEV_CLOSE\fR, \fBPDEV_READ\fR, \fBPDEV_WRITE\fR,
\fBPDEV_IOCTL\fR, \fBPDEV_SET_ATTR\fR, \fBPDEV_GET_ATTR\fR.
.AP int (*handler)() in
Service call-back procedure.
.AP int (*func)() in
A procedure applied to each stream to the pseudo-device.
.BE
.SH Pdev_Open
.LP
\fBPdev_Open\fR creates a pseudo-device
and installs a set of service procedures for it.
The pseudo-device can subsequently be opened by any number of
regular (client) processes,
and the service call-backs are made each time a client process makes
a file system operation on the pseudo-device.
Thus the service call-backs implement the standard file system
operations for the pseudo-device while the Pdev package
manages the interface between the kernel and the server process.
.LP
There are two ways that \fBPdev_Open\fR can pick the name of the file to
use for the pseudo-device. If \fIrealNamePtr\fR is NULL, then
\fBPdev_Open\fR uses \fIname\fR as the name. If \fIrealNamePtr\fR isn't
NULL, then \fBPdev_Open\fR will generate a file name of the form
\fIhostDir\fB/\fInameXX\fR, where \fIhostDir\fR is the name of
a standard host-specific directory, \fIname\fR
is the parameter to this procedure, and \fIXX\fR is a decimal number
generated by \fBPdev_Open\fR. \fBPdev_Open\fR tries numbers up from 1 until it finds
one that works. The name of the successful pseudo-device file is
returned by storing a pointer to it at \fI*realNamePtr\fR; the
storage for the name is dynamically allocated with \fBmalloc\fR and
must eventually be freed by the caller.
.PP
\fBPdev_Open\fR returns an opaque token that
is used in calls to \fBPdev_Close\fP, \fBPdev_SetDefaultHandler\fP,
and \fBPdev_EnumStreams\fP.
If a pseudo-device couldn't be opened, then NULL is
returned and \fBpdev_ErrorMsg\fR contains a string
describing the problem.
.PP
After a successful \fBPdev_Open\fP call the Pdev package will set up a
\fIservice stream\fP whenever a client process
opens the pseudo-device. Each service stream is identified
to the call-backs by a \fBPdev_Stream\fP record.
Thus the pseudo-device can be multiplexed over several clients
with each client's request comming over a different service stream.
However, forks and dups are not visible to the pseudo-device server,
so more than one process might be using any particular service stream.
.PP
The \fIreqBufSize\fP is used to configure a request buffer associated
with each service stream. This size determines how many request messages
can be buffered before the kernel is forced to wait for them to be
serviced. More than one request may be outstanding due to asynchronous writes,
which are described below.
A minimum size on the request buffer is enforced by the library,
so zero can be passed in to get a default size (about 1 Kbyte).
.PP
The \fIreadBufSize\fP is used to configure an optional read buffer associated
with each service stream. If this size is non-zero it indicates that
a read buffer will be used to satisfy client read requests instead
of using the read service call-back.
In this case the Pdev package will allocate
a read buffer each time a service stream is created and pass the address
of this buffer to the open call-back. After that it is up to the
server process to manage the read buffer. See the device man page
for \fBpdev\fP for details.
.PP
The \fIclientData\fP parameter to \fBPdev_Open\fP
is passed to the open call-back as
described below. It is meant to be used as a pointer back to
some top-level state of the pseudo-device.
.LP
The Pdev package uses the facilities of \fBFs_Dispatch\fR in order to keep
track of the streams associated with the pseudo-device and ensure
that Pdev is notified whenever those streams become readable. In order
to use Pdev, you must also use \fBFs_Dispatch\fR.
.SH Pdev_Close
.LP
\fBPdev_Close\fR shuts down a pseudo-device, closing all the streams
associated with it and releasing any resources allocated to the
pseudo-device. As a side-effect the close call-back is made to
any existing service streams. After this procedure returns, \fIpdevToken\fR
should never be used again.
.SH Pdev_GetStreamID
.LP
\fBPdev_GetStreamID\fR returns the identifier for the stream
associated with the token returned by \fBPdev_Open\fP. This may be
used for stream-oriented calls such as \fBfstat\fP but should not be
used as the argument to \fBclose\fP (\fBPdev_Close\fP should be used
instead.)
.SH "Pdev_EnumStreams"
.PP
The \fBPdev_EnumStreams\fP procedure is used to apply a function
to all the service streams to the pseudo-device. This
enumeration procedure eliminates the need to keep track of
each service stream.
The \fIfunc\fP argument is called on each service stream as follows:
.DS
int
(*func)(streamPtr, clientData)
Pdev_Stream *streamPtr;
ClientData clientData;
.DE
Where \fIstreamPtr\fP identifies the service stream,
and \fIclientData\fP is what was passed to \fBPdev_EnumStreams\fP.
\fIfunc\fP should return zero to mean success,
or a non-zero error status. In the case of an error
\fBPdev_EnumStreams\fP stops its enumeration and returns the non-zero status.
.SH "Pdev_SetDefaultHandler"
.LP
\fBPdev_SetDefaultHandler\fP is used to set the call-back for individual
pdev operations.
It is not normally needed as you can define all
the call-backs with \fBPdev_Open\fP (or \fBPfs_OpenConnection\fP).
The call-backs passed to \fBPdev_Open\fP are inherited by
each service stream that is created. Changing a call-back
with \fBPdev_SetDefaultHandler\fP changes the call-back for
all subsequently created service streams. It doesn't affect any
service streams that are already established.
This returns the old default call-back.
.SH Pdev_SetStreamHandler
.PP
\fBPdev_SetStreamHandler\fP is used to set a call-back for an
already existing service stream.
It returns the old call-back.
.SH "SERVICE PROCEDURES"
.ta 1.5i 3.0i 3.5i
.PP
The call-back service procedures are given to \fBPdev_Open\fP
(and \fBPfs_OpenConnection\fP) as a record
of procedures:
.DS
typedef struct {
int (*open)(); /* PDEV_OPEN */
int (*read)(); /* PDEV_READ */
int (*write)(); /* PDEV_WRITE and PDEV_WRITE_ASYNC */
int (*ioctl)(); /* PDEV_IOCTL */
int (*close)(); /* PDEV_CLOSE */
int (*getAttr)(); /* PDEV_GET_ATTR */
int (*setAttr)(); /* PDEV_SET_ATTR */
} Pdev_CallBacks;
.DE
.PP
Any of the record elements can
be NULL to indicate that the operation should be handled by
a default handler.
The \fIservice\fP parameter
itself can also be NULL to indicate default
handling for all operations. This is only useful during initial test.
If a client makes an operation for which no service procedure is provided
it is simply a no-op; it is not an error.
The global variable \fBpdev_Trace\fP can be set to a non-zero value
to generate printfs to stderr when
each service procedure (default or user-supplied) is invoked.
.LP
Service procedures should return zero to mean successful completion,
otherwise they should return an appropriate errno value.
Additionally, the \fBread\fP and \fBwrite\fP procedures
use \fBEWOULDBLOCK\fR to indicate incomplete operations.
This is described further below.
.LP
Each service procedure also sets the current select state bits for
the pseudo-device.
The select bits are used in the kernel's implementation
of \fBselect\fR for pseudo-devices. They should be a bitwise or
combination of \fBFS_READABLE\fR, \fBFS_WRITABLE\fR, and \fBFS_EXCEPTION\fR.
As well as setting this select state after each client operation,
it may be set asynchronously with the \fBIOC_PDEV_READY\fP
\fBioctl\fR command on the service stream.
.PP
These same service procedures are used for
pseudo-device connections into the pseudo-file-system.
See \fBPfs_Open\fP and \fBPfs_OpenConnection\fP.
The \fBgetAttr\fP and \fBsetAttr\fP call-backs are only made to
pseudo-file-system servers.
For regular pseudo-devices the kernel takes care of all attribute handling.
.SH open
.ta 0.5i 3.0i 3.5i
.DS
int
(*service->open)(clientData, streamPtr, readBuffer, flags, procID,
hostID, uid, selectBitsPtr)
ClientData clientData; /* Private data passed to Pdev_Open */
Pdev_Stream *streamPtr; /* Identifies stream to pseudo-device. */
char *readBuffer; /* Storage for optional read buffer */
int flags; /* Flags to the open system call. NOTE!
* These are Sprite flags defined in <fs.h>,
* not the Unix flags defined in <sys/file.h> */
int procID; /* ID of process opening the pseudo-device */
int hostID; /* Host where that process is executing */
int uid; /* User ID of that process */
int *selectBitsPtr; /* Return - the initial select state of the process */
.DE
.LP
When a client process makes an \fBopen\fP system call on the pseudo-device
the Pdev library package invokes the \fBopen\fP service call-back to
give the server a chance to refuse or
accept the open by the client process. The return value of the
open call-back is either 0 for success, or an appropriate errno value.
.PP
The \fBopen\fR call-back gets passed the \fIclientData\fP that was given
to the \fBPdev_Open\fP procedure,
and a new \fIstreamPtr\fP that is a handle on the service stream
corresponding to the open by the client.
\fIstreamPtr\fP is a pointer to a \fBPdev_Stream\fP
record that contains a \fBclientData\fP field for use by the call-backs,
and a \fBstreamID\fP field that is used in \fBioctl\fP calls
on the service stream.
The possible \fBioctl\fP calls are listed at the end of this man page.
The \fIstreamPtr\fP gets passed to all the other call-backs,
and is also passed to \fBPdev_SetStreamHandler\fP.
.PP
The parameters also include the
useFlags passed to the \fBFs_Open\fP system call, and the user ID
and Sprite hostID of the client process.
(\fBFs_Open\fR is the Sprite version of \fBopen\fR. The
flag bits are different and are defined in <fs.h>. Flags passed
to \fBopen\fP are mapped to the Sprite flag bits you'll get here.)
If the \fIreadBufSize\fP parameter to \fBPdev_Open\fP was non-zero then
Pdev allocates \fIreadBuffer\fP and passes it to the open call-back.
Thus there will be one read buffer for each service stream
if the server is implementing read buffering.
.SH close
.ta 0.5i 3.0i 3.5i
.DS
int
(*service->close)(streamPtr)
Pdev_Stream *streamPtr; /* Identifies service stream */
.DE
.LP
This is called when a service stream is closed.
This happens either as a side effect of \fBPdev_Close\fP,
or when the client has closed is last reference to the service stream.
(Dups and forks are not visible to the pseudo-device server,
so there is only one close per open system call by a client process.)
.SH read
.ta 0.5i 3.0i 3.5i
.DS
int
(*service->read)(streamPtr, readPtr, freeItPtr, selectBitsPtr, sigPtr)
Pdev_Stream *streamPtr; /* Identifies service stream */
Pdev_RWParam *readPtr; /* Read parameter block */
Boolean *freeItPtr; /* Set to TRUE if buffer should be free'd */
int *selectBitsPtr; /* Return - select state of the pseudo-device */
Pdev_Signal *sigPtr; /* Return - signal to generate, if any */
.DE
.LP
The read service procedure is passed a record of type \fBPdev_RWParam\fP
that indicates the \fBlength\fP, \fBoffset\fP, and \fBbuffer\fP
for the read.
The buffer is pre-allocated by the \fBPdev\fP library.
If the read service procedure wants to use a different buffer
it can change \fIreadPtr\fB->buffer\fR to reference its own storage.
If this different storage area ought to be freed after
the library completes the operation,
then *\fIfreeItPtr\fR should be set to a non-zero value.
.PP
The \fIreadPtr\fB->length\fR record field indicates how much data is requested,
and it should be updated to reflect the amount of data actually returned.
If there is no data available on the pseudo-device then the
read call-back should return \fBEWOULDBLOCK\fR
and set \fIreadPtr\fB->length\fR to zero.
This causes the kernel to block the client process until the select
state of the pseudo-device is changed to indicate readability.
If there are some bytes available the return value should be zero
and \fIreadPtr\fB->length\fR set appropriately.
If the read leaves no additional bytes available
then the \fBFS_READABLE\fP bit can be cleared from *\fIselectBitsPtr\fP
in order to block the next read request.
End-of-file is indicated to the client by a zero return code and
a zero number of bytes returned.
.PP
A signal can be generated in response to a read request by
setting \fIsigPtr\fB->signal\fR to a non-zero value.
\fIsigPtr\fB->code\fR can also be set to modify the signal meaning.
Data can be returned if a signal is generated.
The client application's system call will complete,
its signal handler, if any, will be invoked,
and the system call will be retried.
.PP
Note: If there is a read buffer associated with the service stream,
which is indicated by a non-zero valued \fIreadBufSize\fP
parameter to \fBPdev_Open\fP,
then this read call-back is never called.
Instead the kernel takes data directly
from the read buffer. The protocol for adding data to the read buffer is
described in the \fBpdev\fR device man page.
.SH write
.ta 0.5i 3.0i 3.5i
.DS
int
(*service->write)(streamPtr, async, writePtr, selectBitsPtr, sigPtr)
Pdev_Stream *streamPtr; /* Identifies service stream */
int async; /* TRUE during an asynchronous write */
Pdev_RWParam *writePtr; /* Write parameter block */
int *selectBitsPtr; /* Return - select state of the pseudo-device */
Pdev_Signal *sigPtr; /* Return - signal to generate, if any */
.DE
.LP
The write service procedure is passed a parameter block that
indicates the \fBlength\fP, \fBoffset\fP, and \fBbuffer\fP
for the operation, plus various IDs of the application process.
If \fIasync\fP is \fBFALSE\fP (zero)
then \fIwritePtr\fB->length\fR should be
updated to reflect how much data was processed by the service procedure.
If \fIasync\fP is non-zero it indicates an asynchronous write and the service
procedure must accept all of the data and the
return value of \fIwritePtr\fB->length\fR is ignored.
.PP
If the server cannot accept all of the data it must return \fBEWOULDBLOCK\fR
\fIand\fP update \fIwritePtr\fB->length\fR to indicate just how much data
it accepted. This return value causes the kernel to block the client
process until the select state of the pseudo-device is changed
to indicate writability.
To repeat, returning a short write count and a zero return code will cause the
kernel to immediately issue another write request to complete
the client's write operation.
By also returning \fBEWOULDBLOCK\fR the pseudo-device server forces the
client process to wait until the pseudo-device becomes writable.
.LP
A signal to the client application can be generated as a side effect
by setting \fIsigPtr\fB->signal\fR to a non-zero value.
\fIsigPtr\fB->code\fR can be set to modify the signal.
Data can be accepted by the write service procedure if a signal is generated.
The client application's write call will complete,
its signal handler, if any, will be invoked,
and the write call will be retried.
.SH ioctl
.ta 0.5i 3.0i 3.5i
.DS
int
(*service->ioctl)(streamPtr, ioctlPtr, selectBitsPtr, sigPtr)
Pdev_Stream *streamPtr; /* Set by open service procedure */
Pdev_IOCParam *ioctlPtr; /* I/O Control parameter block */
int *selectBitsPtr; /* Return - select state of pdev */
Pdev_Signal *sigPtr; /* Return - signal to generate, if any */
.DE
.LP
The ioctl service procedure takes a parameter block that specifies
the \fBcommand\fP, and two buffers,
one containing input data (\fBinBuffer\fP),
and one for data returned to the client (\fBoutBuffer\fP).
The ioctl service has to set \fIioctlPtr\fB->outBufSize\fR to indicate how much
data is being returned to the client process.
The \fBPdev_IOCParam\fP struct also contains various processIDs,
and the \fBformat\fP of the host on which the client
application is executing.
.LP
The pseudo-device server can implement any \fIioctlPtr\fB->command\fR it wants.
Generic commands are defined in <fs.h>, and other ranges of commands
for particular devices and pseudo-devices are defined in header
files in /sprite/src/lib/include/dev.
.LP
The input and output data is not byteswapped by the operating system.
It is the server's responsibility to fix up the input and output
buffers in the case that the client has a different byte order.
The local byte order is defined as \fBMACH_BYTE_ORDER\fR by <machparam.h>,
and the client's byte order and alignment are
indicated by \fIioctlPtr\fB->format\fR.
The \fBFmt_Convert\fR library routine can be used to
swap and align incomming and outgoing buffers.
.LP
A signal to the client application can be generated as a side effect
by setting \fIsigPtr\fB->signal\fR to a non-zero value.
\fIsigPtr\fB->code\fR can be set to modify the signal.
.SH getAttr
.ta 0.5i 3.0i 3.5i
.DS
int
GetAttrProc(streamPtr, attrPtr, selectBitsPtr)
Pdev_Stream *streamPtr; /* Identifies service stream */
Fs_Attributes *attrPtr; /* Return - attributes */
int *selectBitsPtr; /* Return - select state of the pseudo-device */
.DE
.LP
This procedure is called to handle an fstat() call on a file
in a pseudo-file system. The \fIstreamPtr\fP parameter identifies the
open stream, and the server should fill in the attributes.
This call-back is not made to regular pseudo-device servers,
only to pseudo-file-system servers.
.SH setAttr
.ta 3.0i 3.5i
.DS
int
SetAttrProc(streamPtr, flags, uid, gid, attrPtr, selectBitsPtr)
Pdev_Stream *streamPtr; /* Identifies service stream */
int flags; /* Indicate what attributes to set */
int uid; /* Identifies user making the call */
int gid; /* Identifies group of process */
Fs_Attributes *attrPtr; /* Attributes to set as indicated by flags */
int *selectBitsPtr; /* Return - select state of the pseudo-device */
.DE
.LP
This procedure is called to set certain attributes of
an open file in a pseudo-file system. The \fIstreamPtr\fP
parameter identifies the open stream.
The flags argument contains an or'd combinantion of
\fBFS_SET_TIMES\fR, \fBFS_SET_MODE\fR, \fBFS_SET_OWNER\fR,
\fBFS_SET_FILE_TYPE\fR, \fBFS_SET_DEVICE\fR
that indicate what attributes to set. The attribute values are contained
in \fI*attrPtr\fR. The \fIuid\fR and \fIgid\fR arguments
identify the calling process.
This call-back is not made to regular pseudo-device servers,
only to pseudo-file-system servers.
.SH Service Stream Ioctls
.ta 1.0i
.PP
The pseudo-device server can make a few \fBFs_IOControl\fP calls on
its service streams. The details of the calling sequences is described
in the device man page for pseduo-devices (pdev). The possible
operations are:
.IP IOC_PDEV_READY
Used to change the select state of the pseudo-device. The input buffer
to Fs_IOControl should contain an or'd combination of
\fBFS_READABLE\fR, \fBFS_WRITABLE\fR, or \fBFS_EXCEPTION\fR.
.IP IOC_PDEV_SIGNAL_OWNER
Used to send a signal to the owning process or process group of the
pseudo-device. This is useful for implementing interrupt characters
in tty emulators. No special permission is needed.
.IP IOC_PDEV_WRITE_BEHIND
Used to set or unset asynchronous writing.
.IP IOC_PDEV_BIG_WRITES
Used to allow or disallow writes larger than the request buffer.
.IP IOC_PDEV_SET_PTRS
Used to adjust pointers into the read buffer and the request buffer.
Users of the Pdev package should only use this to adjust
read buffer pointers. Leave the request buffer pointers equal to -1
so you don't mess up the managing of the request buffer.
.PP
For example:
.DS
status = Fs_IOControl(streamPtr->streamID, IOC_PDEV_READY,
sizeof(int), &selectBits, 0, NULL);
.DE
.SH SEE ALSO
pdev (devices), Pfs, Swap_Buffer
.SH KEYWORDS
pseudo-device